package com.qinggeng.project.api.controller;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.qinggeng.common.constant.Constants;
import com.qinggeng.common.enums.AssistStatusEnum;
import com.qinggeng.common.enums.CommandTypeEnum;
import com.qinggeng.common.enums.ShowTypeEnum;
import com.qinggeng.common.exception.CustomException;
import com.qinggeng.common.utils.DateUtils;
import com.qinggeng.framework.config.mq.MQSendUtils;
import com.qinggeng.framework.config.mq.dto.MessageAssistDTO;
import com.qinggeng.framework.config.mq.enums.MQTypeEnum;
import com.qinggeng.framework.redis.RedisCache;
import com.qinggeng.framework.web.controller.BaseController;
import com.qinggeng.framework.web.domain.AjaxResult;
import com.qinggeng.project.api.dto.AssistRecordDto;
import com.qinggeng.project.api.dto.AssistUserInformationDto;
import com.qinggeng.project.api.security.annotation.LoginRequired;
import com.qinggeng.project.api.security.utils.ApiUtils;
import com.qinggeng.project.api.utils.CommandUtils;
import com.qinggeng.project.system.domain.*;
import com.qinggeng.project.system.service.*;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * @author 吴鹏飞
 * @date 2020/11/5
 */
@Api(tags = "助力模块")
@RestController
@RequestMapping("${apiPath}/assist")
@Slf4j
public class ApiAssistController extends BaseController {
    @Autowired
    private IAssistRecordService assistRecordService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private IGoodsService goodsService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private IAssistHelpService assistHelpService;
    @Autowired
    private IGiftProbabilityService giftProbabilityService;
    @Autowired
    private ISysConfigService configService;
    @Resource
    private MQSendUtils mqSendUtils;
    @Resource
    private RedissonClient redissonClient;

    @ApiOperation("获取用户商品助力信息")
    @GetMapping("/goodsAssistInformation")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "助力id", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "", response = AssistUserInformationDto.class)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult goodsAssistInformation(Long id) {
        try {
            //查询助力记录
            AssistRecord assistRecord = assistRecordService.selectAssistRecordById(id);
            if (assistRecord == null) {
                return AjaxResult.error("助力记录不存在 id=" + id);
            }
            if (assistRecord.getUserId().equals(ApiUtils.getUserId())) {
                return AjaxResult.error("此口令属于本用户");
            }
            //查询商品信息
            Goods goods = goodsService.selectGoodsById(assistRecord.getGoodsId());
            if (goods == null) {
                return AjaxResult.error("商品信息不粗在 goods=" + goods);
            }

            //查询用户信息
            SysUser sysUser = sysUserService.selectUserById(assistRecord.getUserId());
            if (sysUser == null) {
                return AjaxResult.error("助力用户信息不存在,sysUser=" + sysUser);
            }

            AssistUserInformationDto assistUserInformationDto = new AssistUserInformationDto();
            assistUserInformationDto.setAvatar(sysUser.getAvatar());
            assistUserInformationDto.setUserName(sysUser.getUserName());
            assistUserInformationDto.setId(id);
            assistUserInformationDto.setGoodsImg(goods.getGoodsImg());
            assistUserInformationDto.setGoodsName(goods.getGoodsName());
            assistUserInformationDto.setUserId(sysUser.getUserId());
            assistUserInformationDto.setGoodsPrice(new BigDecimal(goods.getGroupPrice() + ""));

            return AjaxResult.success(assistUserInformationDto);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("系统异常:" + e.getMessage());
        }
    }

    @ApiOperation("用户商品助力状态")
    @GetMapping("/goodsAssistStatus")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "mainCategory", value = "商品主类", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(name = "shopId", value = "商户id", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = false)
    })
    @LoginRequired(must = false)
    public AjaxResult goodsAssistStatus(Long shopId, Long mainCategory) {
        try {
            if (shopId != 6L) {
                return AjaxResult.error("商家错误，shopId = " + shopId);
            }
            String url = (String) configService.selectConfigByKey("sys.gift.drawUrl");
            if (!ApiUtils.getIsLogin()) {
                HashMap<String, String> data = Maps.newHashMap();
                //助力状态 0=未申请助力 2=助力中 1=助力成功
                data.put("assistStatus", "0");
                data.put("outTime", "");
                data.put("remainCount", "");
                data.put("id", "");
                data.put("url", "");
                data.put("goodsId", "");
                data.put("mainCategory", "");
                return AjaxResult.success(data);
            }
            HashMap<String, String> data = Maps.newHashMap();
            //查询主分类id是否有记录
            AssistRecord assistRecord = assistRecordService.selectAssistRecordByMainCategory(ApiUtils.getUserId(), mainCategory);
            if (assistRecord != null) {
                if (assistRecord.getAssistSuccess().equals(AssistStatusEnum.助力成功.getStatus())) {
                    data.put("assistStatus", "1");
                    data.put("outTime", assistRecord.getOutTime().getTime() + "");
                    Integer remainCount = redisCache.getCacheObject("ASSIST_ID:" + assistRecord.getId());
                    if (remainCount != 0) {
                        return AjaxResult.error("assistStatus=1,但剩余助力次数不等于0,remainCount=" + remainCount);
                    }
                    data.put("remainCount", remainCount + "");
                    //助力id
                    data.put("id", assistRecord.getId() + "");
                    data.put("url", url);
                    data.put("goodsId", "");
                    data.put("mainCategory", "");
                } else if (assistRecord.getAssistSuccess().equals(AssistStatusEnum.进行中.getStatus())) {
                    data.put("assistStatus", "2");
                    data.put("outTime", assistRecord.getOutTime().getTime() + "");
                    data.put("remainCount", redisCache.getCacheObject("ASSIST_ID:" + assistRecord.getId()));
                    //助力id
                    data.put("id", assistRecord.getId() + "");
                    data.put("url", url);
                    data.put("goodsId", assistRecord.getGoodsId() + "");
                    data.put("mainCategory", assistRecord.getMainCategory() + "");
                }
            } else {
                //助力状态 0=未申请助力 2=助力中 1=助力成功
                data.put("assistStatus", "0");
                data.put("outTime", "");
                data.put("remainCount", "");
                data.put("id", "");
                data.put("url", "");
                data.put("goodsId", "");
                data.put("mainCategory", "");
            }
            return AjaxResult.success(data);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("goodsAssistStatus()+" + e.getMessage());
            return AjaxResult.error("系统繁忙，请稍后");
        }

    }

    @ApiOperation("帮助力")
    @PostMapping("/helpsAssist")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "助力Id", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult helpsAssist(Long id) {
        RLock lock = redissonClient.getLock("HELPASSIST_ID_LOCK_" + id);
        lock.lock();
        try {
            //查询为过期的助力记录
            AssistRecord assistRecord = assistRecordService.selectAssistRecordById(id);
            if (assistRecord == null) {
                return AjaxResult.error("当前助力商品不存在", ShowTypeEnum.用户.getValue());
            }
            if (ApiUtils.getUserId().equals(assistRecord.getUserId())) {
                return AjaxResult.error("申请人不能参加助力", ShowTypeEnum.用户.getValue());
            }
            //过期
            if (assistRecord.getOutTime().getTime() < DateUtils.getNowDate().getTime()) {
                return AjaxResult.error("当前助力商品已过期,请重新申请", ShowTypeEnum.用户.getValue());
            }
            if ((Integer) redisCache.getCacheObject("ASSIST_ID:" + assistRecord.getId()) == 0) {
                return AjaxResult.error("已助力成功,可以参与抽奖了!", ShowTypeEnum.用户.getValue());
            }
            AssistHelp assistHelp = new AssistHelp();
            assistHelp.setUserId(ApiUtils.getUserId());
            //查询帮捶用户当天帮捶记录
            List<AssistHelp> assistHelps = assistHelpService.selectAssistHelpListByToday(assistHelp);
            //判断是否参与助力
            if (assistHelps != null && assistHelps.size() > 0) {
                //获取字典数据，帮助力次数
                JSONObject jsonObject = JSONObject.parseObject((String)
                        configService.selectConfigByKey("sys.assist.count"));
                int count = Integer.parseInt(jsonObject.getString("count"));
                //判断是否达到次数
                if (assistHelps.size() >= count){
                    return AjaxResult.error("今天助力次数已达上限",ShowTypeEnum.用户.getValue());
                }
                //判断是否助力此商品
                for (AssistHelp help : assistHelps) {
                    if (help.getAssistId().equals(id)) {
                        return AjaxResult.error("您已助力过,谢谢参与!", ShowTypeEnum.用户.getValue());
                    }
                }
            }

            assistHelp.setAssistId(id);
            assistHelpService.insertAssistHelp(assistHelp);

            //已捶次数加一
            assistRecord.setAlreadyAssistCount(assistRecord.getAlreadyAssistCount()+1);
            assistRecordService.updateAssistRecord(assistRecord);
            //获取次数并扣减
            if ((Integer) redisCache.getCacheObject("ASSIST_ID:" + id) <= 0){
                throw new CustomException("助力结束");
            }
            redisTemplate.opsForValue().decrement("ASSIST_ID:" + id);
            redisTemplate.expireAt("ASSIST_ID:" + id, assistRecord.getOutTime());
            if ((Integer) redisCache.getCacheObject("ASSIST_ID:" + id) == 0) {
                assistRecord.setAssistSuccess("1");
                assistRecordService.updateAssistRecord(assistRecord);
            }

            return AjaxResult.success("助力成功", ShowTypeEnum.用户.getValue());

        } catch (Exception e) {
            e.printStackTrace();
            log.error("helpsAssist()" + e.getMessage());
            return AjaxResult.error("系统繁忙,请稍后");
        } finally {
            lock.unlock();
        }
    }

    @ApiOperation("申请助力")
    @PostMapping("/applyAssist")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "goodsId", value = "商品id", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(name = "mainCategory", value = "主类id", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(name = "judge", value = "1=申请助力 2=再次申请口令", dataType = "String", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult applyAssist(Long goodsId, Long mainCategory, String judge,String adCode) {
        RLock lock = redissonClient.getLock("APPLYASSIST:" + goodsId + ApiUtils.getUserId());
        if (lock.isLocked()){
            return AjaxResult.error("已申请，勿重复操作",ShowTypeEnum.用户.getValue());
        }
        lock.lock();
        try {
            //查询这类商品是否正在助力
            AssistRecord oldAssistRecord = assistRecordService.selectAssistRecordByMainCategory(ApiUtils.getUserId(), mainCategory);
            if ("1".equals(judge)) {
                if (oldAssistRecord != null) {
                    if (oldAssistRecord.getAssistSuccess().equals(AssistStatusEnum.进行中.getStatus())) {
                        return AjaxResult.error("您选择的这类商品，正在进行中，请完成后在申请助力！");
                    } else if (oldAssistRecord.getAssistSuccess().equals(AssistStatusEnum.助力成功.getStatus())) {
                        return AjaxResult.error("您选择的这类商品已助力成功，请完成抽奖后在申请助力！");
                    }
                }
            } else if ("2".equals(judge)) {
                String command = CommandUtils.getCommand(CommandTypeEnum.好友助力.getValue(), oldAssistRecord.getId() + "", redisCache,adCode);
                HashMap<String, String> data = Maps.newHashMap();
                data.put("command", command);
                data.put("id", oldAssistRecord.getId() + "");
                data.put("outTime", oldAssistRecord.getOutTime().getTime() + "");
                data.put("remainCount", redisCache.getCacheObject("ASSIST_ID:" + oldAssistRecord.getId()));
                return AjaxResult.success(data);
            }

            Goods goods = goodsService.selectGoodsById(goodsId);
            if (goods == null) {
                return AjaxResult.error("商品不存在,goodsId=" + goodsId);
            }
            BigDecimal goodPrice = new BigDecimal(goods.getGroupPrice() + "");
            Integer assistCount = null;
            GiftProbability giftProbability = giftProbabilityService.selectHelpNumByGoodsPrice(goodPrice);
            if (giftProbability == null){
                throw new CustomException("助力次数错误");
            }
            assistCount = giftProbability.getHelpNum();
            if (assistCount == null) {
                return AjaxResult.error("助力次数异常assistCount=" + assistCount);
            }

//            if (Constants.DEBUG) {
//                assistCount = 1;
//            }

            AssistRecord assistRecord = new AssistRecord();
            assistRecord.setUserId(ApiUtils.getUserId());
            assistRecord.setGoodsId(goodsId);
            assistRecord.setMainCategory(mainCategory);
            assistRecord.setAssistCount(assistCount);
            //助力状态为进行中
            assistRecord.setAssistSuccess("2");
            Date nowDate = DateUtils.getNowDate();
            assistRecord.setCreateTime(nowDate);
            //设置过期时间为24小时
//            Date outDate = new Date(nowDate.getTime() + 24 * 60 * 60 * 1000);
            JSONObject otherParams = JSONObject.parseObject(configService.selectConfigByKey("sys.assist.time").toString());
            long time = Long.parseLong(otherParams.getString("time"));
            Date outDate = new Date(nowDate.getTime() + time * 1000);
            assistRecord.setOutTime(outDate);
            assistRecordService.insertAssistRecord(assistRecord);

            //发送延时消息
            MessageAssistDTO messageModel = new MessageAssistDTO();
            messageModel.setMessageId(IdUtil.getSnowflake(1l,1l).nextId());
            messageModel.setType(MQTypeEnum.ASSIST_FAIL_HANDLE.getType());
//            messageModel.setDelayTime(24 * 60 * 60L);
            messageModel.setDelayTime(time);
            messageModel.setId(assistRecord.getId());

//            mqSendUtils.sendDelayMessage(messageModel,24 * 60 * 60L);
            mqSendUtils.sendDelayMessage(messageModel,time);


            //设置缓存
            redisCache.setCacheObject("ASSIST_ID:" + assistRecord.getId(), assistCount);
            redisTemplate.expireAt("ASSIST_ID:" + assistRecord.getId(), outDate);
            String id = assistRecord.getId() + "";
            //20助力
            String command = CommandUtils.getCommand(CommandTypeEnum.好友助力.getValue(), id, redisCache,adCode);
            HashMap<String, String> data = Maps.newHashMap();
            data.put("command", command);
            data.put("id", id);
            data.put("outTime", outDate.getTime() + "");
            data.put("remainCount", assistCount + "");

            return AjaxResult.success(data);
        } catch (Exception e) {

            e.printStackTrace();
            log.error("applyAssist()" + e.getMessage());
            return AjaxResult.error("系统繁忙，请稍后");
        }finally {
            lock.unlock();
        }
    }

    @ApiOperation("助力列表")
    @GetMapping("/goodsAssistList")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "assistIndex", value = "2=助力中 1=助力成功 0=助力失败", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @ApiResponses({
            @ApiResponse(code = 200, message = "", response = AssistRecordDto.class)
    })
    @LoginRequired(role = ApiUtils.DEFAULT_ROLE_USER)
    public AjaxResult goodsAssistList(String assistIndex) {
        try {
            //根据条件查询用户助力列表
            String url = (String) configService.selectConfigByKey("sys.gift.drawUrl");

            startPage();
            List<AssistRecordDto> assistRecords = assistRecordService.selectAssistRecordByUserIdAndAssistIndex(ApiUtils.getUserId(), assistIndex);
            if (assistRecords != null && assistRecords.size() > 0) {
                for (AssistRecordDto assistRecord : assistRecords) {
                    assistRecord.setOutTimeMs(assistRecord.getOutTime().getTime());
                    if (assistIndex.equals("2")) {
                        assistRecord.setRemainCount(redisCache.getCacheObject("ASSIST_ID:" + assistRecord.getId()));
                    }
                    if (assistIndex.equals("1")) {
                        assistRecord.setUrl(url);
                    }
                }
            }
            if (assistRecords == null) {
                assistRecords = new ArrayList<>();
            }
            return AjaxResult.success(assistRecords);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("goodsAssistList=" + e.getMessage());
            return AjaxResult.error("系统异常");
        }
    }

    @ApiOperation("删除记录")
    @GetMapping("/delAssistRecord")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "助力id", dataType = "long", paramType = "query", required = true),
            @ApiImplicitParam(paramType = "header", dataType = "String", name = Constants.TOKEN, value = "token标记", required = true)
    })
    @LoginRequired
    public AjaxResult delAssistRecord(Long id) {
        try {
            //逻辑删除
            assistRecordService.deleteAssistRecordById(id);
            return AjaxResult.success("删除成功", ShowTypeEnum.用户.getValue());
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("系统异常" + e.getMessage());
        }
    }

    //放弃抽奖
    @GetMapping("/abandonPrize")
    @LoginRequired
    @CrossOrigin
    public AjaxResult abandonPrize(Long id){
        try {
            AssistRecord assistRecord = new AssistRecord();
            assistRecord.setId(id);
            //助力失败
            assistRecord.setAssistSuccess("0");
            assistRecordService.updateAssistRecord(assistRecord);
            return AjaxResult.success();
        } catch (Exception e) {
            log.info(e.getMessage());
            return AjaxResult.error(e.getMessage());
        }
    }
}
